import { copyFileSync, readdirSync, readFileSync, renameSync, statSync, writeFileSync } from "fs";
import path, { basename, extname, join } from "path";
import { cpDir, cpFile, mkdirsSync } from "../../utils/CpFile";
import { getJsList } from "../../utils/PaserFile";
import { BasePack } from "../BasePack";
import { IOppoPackageOptions } from "../IPack";
import * as zipper from "zip-local";
import { getTodaytr } from "../../utils/TimeUtil";

export class OppoPack extends BasePack {

    protected _packOpt: IOppoPackageOptions;
    protected _jsList: string[]

    constructor(packProjectJsonName: string) {
        super(packProjectJsonName);
        this._projectConfigFile = 'manifest.json';
        this._layaEnginePlugins = [];
    }

    protected _copyInitDir(from: string, out: string) {
        this._packOpt = this._projCfg[this._mode]['packageOptions'];

        cpDir(from, out, () => {
            // 需要修改一下 project.config.json 中的替换文本
            // let pcfUrl = `${this._plat}/${this._plat}game/${this._projectConfigFile}`;
            // let pcfTemp = join(this._packOpt.outputPath, pcfUrl);
            // let jsonStr = readFileSync(pcfTemp).toString();

            // jsonStr = jsonStr.replace('PACKAGE_HOLD', this._packOpt.packageId)
            // jsonStr = jsonStr.replace('NAME_HOLD', this._packOpt.gameName);
            // jsonStr = jsonStr.replace('VERSION_NAME_HOLD', this._packOpt.versionName);
            // jsonStr = jsonStr.replace('VERSION_HOLD', this._packOpt.versionCode + '');
            // jsonStr = jsonStr.replace('PLATVER_HOLD', this._packOpt.minPlatformVersion + '');
            // let icomName = basename(join(this._packOpt.iconPath));
            // jsonStr = jsonStr.replace('ICON_HOLD', icomName);
            // jsonStr = jsonStr.replace('ORIENTATION_HOLD', this._packOpt.orientation);
            // writeFileSync(pcfTemp, jsonStr);

            // let fromIndex = join(this._packOpt.projectBin, 'index.js');
            // let jslist = this._jsList = getJsList(fromIndex);
            // let jsStr = 'require("config.js");\n';
            // jslist.forEach(js => {
            //     if (!js) return;
            //     jsStr += `require("${js}");\n`;
            // })

            // // 修改 oppo包中的 main.js
            // let mainjs = join(this._packOpt.outputPath, `${this._plat}/${this._plat}game`, 'main.js');
            // let gamejsTxt = readFileSync(mainjs).toString();
            // gamejsTxt = gamejsTxt.replace("/**REQUIRE_HOLD*/", jsStr);
            // writeFileSync(mainjs, gamejsTxt);

            // // 将logo拷贝到导出目录
            // let fromIconUrl = join(this._packOpt.iconPath);
            // let outIconUrl = join(this._packOpt.outputPath, `${this._plat}/${this._plat}game`, basename(fromIconUrl));
            // copyFileSync(fromIconUrl, outIconUrl);

            this._startPack(this._packOpt);
        })
    }

    protected _resetManifest() {
        let from = this._getTemplateUrl();
        let fromManifest = join(from, this._projectConfigFile);

        let pcfUrl = `${this._plat}/${this._plat}game/${this._projectConfigFile}`;
        let pcfTemp = join(this._packOpt.outputPath, pcfUrl);
        let jsonStr = readFileSync(fromManifest).toString();

        jsonStr = jsonStr.replace('PACKAGE_HOLD', this._packOpt.packageId)
        jsonStr = jsonStr.replace('NAME_HOLD', this._packOpt.gameName);
        jsonStr = jsonStr.replace('VERSION_NAME_HOLD', this._packOpt.versionName);
        jsonStr = jsonStr.replace('VERSION_HOLD', this._packOpt.versionCode + '');
        jsonStr = jsonStr.replace('PLATVER_HOLD', this._packOpt.minPlatformVersion + '');
        let icomName = basename(join(this._packOpt.iconPath));
        jsonStr = jsonStr.replace('ICON_HOLD', icomName);
        jsonStr = jsonStr.replace('ORIENTATION_HOLD', this._packOpt.orientation);
        writeFileSync(pcfTemp, jsonStr);
    }
    protected _resetMainJs() {
        let fromIndex = join(this._packOpt.projectBin, 'index.js');
        let jslist = this._jsList = getJsList(fromIndex);
        let jsStr = 'require("config.js");\n';
        jslist.forEach(js => {
            if (!js) return;
            jsStr += `require("${js}");\n`;
        })

        // 修改 oppo包中的 main.js
        let from = this._getTemplateUrl();
        let fromMainJs = join(from, 'main.js')
        let mainjs = join(this._packOpt.outputPath, `${this._plat}/${this._plat}game`, 'main.js');
        let gamejsTxt = readFileSync(fromMainJs).toString();
        gamejsTxt = gamejsTxt.replace("/**REQUIRE_HOLD*/", jsStr);
        writeFileSync(mainjs, gamejsTxt);
    }

    protected _resetIcon() {
        let fromIconUrl = join(this._packOpt.iconPath);
        let outIconUrl = join(this._packOpt.outputPath, `${this._plat}/${this._plat}game`, basename(fromIconUrl));
        copyFileSync(fromIconUrl, outIconUrl);
    }

    protected _startPack(packOpt: any) {
        this._packOpt = packOpt;
        console.log('ready start pack ...');

        this._resetManifest();
        this._resetMainJs();
        this._resetIcon();

        this._minigamePath = join(this._packOpt.outputPath, `${this._plat}/${this._plat}game`);
        let jslist: string[];
        if (this._jsList) {
            jslist = this._jsList
        } else {
            let fromIndex = join(this._packOpt.projectBin, 'index.js');
            jslist = this._jsList = getJsList(fromIndex);
        }

        // 将index中的需要用到的js拷贝到oppogame项目中
        let from: string[] = [];
        let to: string[] = [];
        jslist.forEach(url => {
            if (!url) return;
            from.push(join(this._packOpt.projectBin, url))
            let libUrl = join(this._minigamePath, url);
            console.log(libUrl);

            to.push(libUrl);
        });

        cpFile(from, to, () => {

            this._setSign(() => {

                if (this._packOpt.skipResCheck) {
                    console.log(this._mode + ' pack over');
                    // this._packOver([this._minigamePath])
                    this._setGameConfig()
                    this._preOver()

                    return;
                } else {
                    this._resPath = this._packOpt.resPath;
                    this._cpResIndex = 0;
                    this._setGameConfig()

                    this._cpRes();
                }
            })

        }, !this._packOpt.skipCodeUglify)

    }
    protected _setSign(cb?: () => void) {
        // prod的模式下,需要拷贝正式签名
        if (!this._packOpt.signPath || this._mode == 'dev') {
            if (!!cb) cb();
            return;
        }
        let from: string[] = [
            join(this._packOpt.signPath, 'certificate.pem'),
            join(this._packOpt.signPath, 'private.pem')
        ];
        let to: string[] = [
            join(this._minigamePath, 'sign/release/certificate.pem'),
            join(this._minigamePath, 'sign/release/private.pem')
        ];
        cpFile(from, to, () => {
            console.log('release sign ok');
            if (!!cb) cb();
        });
    }

    protected _setGameConfig() {
        let config: any = this._projCfg[this._mode]['config'];

        if (!config) {
            config = {};
            return;
        }
        let txt = `window.config = ${JSON.stringify(config)};`;
        let po = this._projCfg[this._mode]['packageOptions'];
        let configUrl = join(po.outputPath, `${this._plat}/${this._plat}game`, 'config.js');
        writeFileSync(configUrl, txt);
    }

    protected _cpRes() {
        if (this._cpResIndex >= this._resPath.length) {
            this._preOver();
            return;
        }
        let pathName = this._resPath[this._cpResIndex]
        let toResUrl = join(this._minigamePath, pathName);
        if (this._packOpt.resVer) {
            toResUrl = join(this._packOpt.outputPath, `${this._plat}/${this._packOpt.resVer}/${pathName}`);
        }
        let tempList = pathName.split('/');
        if (tempList[tempList.length - 1].indexOf('.') >= 0) {
            // 是文件
            mkdirsSync(path.dirname(toResUrl))
            copyFileSync(join(this._packOpt.projectBin, pathName), toResUrl);
            console.log(this._mode + ' cp file about: ' + pathName);
            this._cpResIndex++;
            this._cpRes()
        } else {
            // 是目录
            cpDir(join(this._packOpt.projectBin, pathName), toResUrl, () => {
                console.log(this._mode + ' cp dir about: ' + pathName);
                this._cpResIndex++;
                this._cpRes()
            })
        }
    }

    protected async _preOver() {
        await this._toCallBuild();
        this._packOver()
    }

    protected async _toCallBuild() {
        // 调用 quickgame pack 
        if (this._mode == 'dev') {
            await this.exec('quickgame pack', { cwd: this._minigamePath })

        } else if (this._mode == 'prod') {
            console.log(`当前打包版本为:\x1b[92m ${this._packOpt.versionName} \x1b[97m,请注意！`);
            await this.exec('quickgame pack release', { cwd: this._minigamePath })
            // 打完正式包，将正式包重命名为其版本号
            this._zipRpk()
        }
    }

    protected _zipRpk() {
        let distName = join(this._minigamePath, 'dist')
        let files = readdirSync(distName);
        for (const ifile of files) {
            let ifurl = path.join(distName, ifile);
            if (statSync(ifurl).isFile() && ifurl.indexOf('.rpk') >= 0) {
                // 如果是.rpk文件
                let ext = extname(ifurl);
                // console.log('base',path.dirname(ifurl));

                if (ifurl.substr(ifurl.length - ext.length, ext.length) == ext) {
                    // let newUrlHead = ifurl.substr(0, ifurl.length - ext.length);
                    // let newUrl = `${newUrlHead}_${this._packOpt.versionName}${extname(ifurl)}`;
                    // renameSync(ifurl, newUrl);
                    let newName = `${this._plat}_${this._packOpt.gameName}_${getTodaytr()}_${this._packOpt.versionName}.zip`;
                    let newUrl = join(path.dirname(ifurl), newName);
                    zipper.sync.zip(ifurl).compress().save(newUrl);

                }
            }
        }
    }
}